#pragma once
#include<iostream>
#include<sys/select.h>
#include<sys/time.h>
#include<string>
#include"Sock.hpp"

#define NUM 1024
#define POST 8081
using namespace std;
class select_servr{
    private:
        int post;
        int listen_sock;
        TcpServer* ptr;
    public:
        select_server(int _post=POST):post(_post),listen_sock(-1)
        {}

        void Start(){
            ptr=TcpServer::getTcpobj(post);
            listen_sock=ptr->isSock();

            int fd_arr[1024]={0};
            int max_fd=0;
            fd_set fdread;
            struct timeval tiemout;

            ClearArr(fd_arr);//初始化fd_arr中的内容为-1
            fd_arr[0]=listen_sock;
            while(true){
                FD_ZERO(&fdread);//清空位图
                tiemout={5,0};
                //把fd_drr中的文件描述符添加到fd_read
                for(int j=0;j<1024;j++){
                    if(fd_arr[j]==-1)
                        continue;
                    else
                        FD_SET(fd_arr[j],&fdread);
                    if(max_fd<fd_arr[j])
                        max_fd=fd_arr[j];
                }
                switch(select(max_fd+1,&fdread,nullptr,nullptr,&tiemout)){
                    case 0:
                        cout<<"没有事件发生"<<endl;
                        break;
                    case -1:
                        cerr<<"select error..."<<endl;
                        break;
                    default:
                        cout<<"有事件发生： "<<tiemout.tv_sec<<endl;
                        for(int i=0;i<1024;i++){
                            if(fd_arr[i]==-1)
                                continue;
                            if(FD_ISSET(fd_arr[i],&fdread) && fd_arr[i]==listen_sock){
                                struct sockaddr_in oth;
                                socklen_t len=sizeof(oth);
                                int sock=accept(listen_sock,(struct sockaddr*)&oth,&len);
                                if(sock<0){
                                    cerr<<"accept error..."<<endl;
                                }
                                else if(!AddArr(fd_arr,sock)){
                                    close(sock);
                                }
                            }
                            else if(FD_ISSET(fd_arr[i],&fdread) && fd_arr[i]!=listen_sock){
                                char buffer[NUM];
                                ssize_t s=recv(fd_arr[i],buffer,NUM-1,0);
                                if(s>0){
                                    buffer[s]=0;
                                    cout<<"echo# "<<buffer<<endl;
                                    // close(fd_arr[i]);
                                    // fd_arr[i]=-1;
                                }
                                else if(s==0){
                                    cout<<"client quit..."<<endl;
                                    close(fd_arr[i]);
                                    fd_arr[i]=-1;
                                }
                                else{
                                    cerr<<"recv error..."<<endl;
                                    close(fd_arr[i]);
                                    fd_arr[i]=-1;
                                }
                            }
                        }
                        break;
                }

            }
        }
        ~select_server(){
            if(listen_sock>=0)
                close(listen_sock);
        }
    private:
        void ClearArr(int* arr){
            for(int i=0;i<1024;i++)
                arr[i]=-1;
        }
        bool AddArr(int* arr,int sock){
            for(int i=0;i<1024;i++){
                if(arr[i]==-1){
                    arr[i]=sock;
                    return true;
                }
            }
            return false;
        }
};